package com.hx.setting.dao.imp;

import com.hx.setting.dao.AbstractJDBCDaoSupport;
import com.hx.setting.dao.BaseDao;
import com.hx.setting.entity.Entity;
import com.hx.setting.model.Condition;
import com.hx.setting.model.GeneratedCriteria.Criterion;
import com.hx.setting.model.GeneratedCriteria;
import com.hx.setting.model.Page;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * dao 基础类
 * Generate Date : 2014-03-16
 * Generate Version : v3.0
 * Generate Name : Honey v3.1 Test
 * Generate User : THINK
 * JDK Version : 1.5
 */
public abstract class JdbcBaseDaoImp<E extends Entity, PK extends Serializable> extends AbstractJDBCDaoSupport implements BaseDao<E, PK>
{

	/** 
	 * 根据条件查询记录集数量。
	 * @param  search {@code   com.onecity.model.Condition<? extends GeneratedCriteria>} 动态查询语句
	 * @return  int
	 * @see    com.onecity.model.Condition<? extends GeneratedCriteria>
	 */
	@Override
	public int count(Condition<? extends GeneratedCriteria> search)
	{
		Integer answer = 0;
		StringBuilder sql = new StringBuilder( "SELECT count(*) FROM " ).append( getTableName() );
		Object[] params = null;
		if ( search != null && search.getOredCriteria().size() == 0 )
		{
			Object[] build = make( search );
			sql.append( " WHERE " ).append( build[0] );
			params = (Object[]) build[1];
		}
		try
		{
			answer = (Integer) query( prepareConnection() ,true ,false ,sql.toString() ,new ResultSetHandler()
			{

				@Override
				public Object handle(ResultSet resultSet, boolean hasBlob) throws SQLException
				{
					Integer answer = 0;
					if ( resultSet.next() )
					{
						answer = resultSet.getInt( 1 );
					}
					return answer;
				}
			} ,params );
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
		}
		return answer;
	}

	/** 
	 * 使用数据库的exists函数判断查询条件是否有记录集。
	 * 在某些条件下可以替换in查询以提高查询效率。
	 * @param  search {@code   com.onecity.model.Condition<? extends GeneratedCriteria>} 动态查询语句
	 * @return  boolean
	 * @see    com.onecity.model.Condition<? extends GeneratedCriteria>
	 */
	@Override
	public boolean exists(Condition<? extends GeneratedCriteria> search)
	{
		Boolean answer = false;
		return answer;
	}

	/** 
	 * 按照主键查询一条记录。
	 * @param  pk 主键
	 * @return  E
	 */
	@Override
	public E selectByPrimaryKey(PK pk)
	{
		E answer = null;
		StringBuilder sql = new StringBuilder( "SELECT " );
		String tmp = getBaseQueryField();
		sql.append( tmp );
		tmp = getBlobQueryField();
		boolean hasBlob = tmp != null && tmp.length() > 0;
		if ( hasBlob )
		{
			sql.append( ',' ).append( tmp );
		}
		sql.append( " FROM " ).append( getTableName() ).append( " WHERE " ).append( getFieldPrimaryKeyName() ).append( "=?" );
		try
		{
			answer = (E) query( prepareConnection() ,true ,hasBlob ,sql.toString() ,getResultSetHandler() ,new Object[]
			{ pk } );
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
		}
		return answer;
	}

	@Override
	public List<E> selectAll()
	{
		return selectList( null ,new Page( -1, -1, -1 ) ,null );
	}

	@Override
	public List<E> selectAll(Page page)
	{
		return selectList( null ,page ,null );
	}

	@Override
	public List<E> selectByDynamic(Condition<? extends GeneratedCriteria> search)
	{
		String condtion = null;
		Object[] params = null;
		if ( search != null && search.getOredCriteria().size() > 0 )
		{
			Object[] build = make( search );
			condtion = (String) build[0];
			params = (Object[]) build[1];
		}
		return selectList( condtion ,new Page( -1, -1, -1 ) ,params );
	}

	@Override
	public List<E> selectByDynamic(Condition<? extends GeneratedCriteria> search, Page page)
	{
		String condtion = null;
		Object[] params = null;
		if ( search != null && search.getOredCriteria().size() > 0 )
		{
			Object[] build = make( search );
			condtion = (String) build[0];
			params = (Object[]) build[1];
		}
		return selectList( condtion ,page ,params );
	}

	/** 
	 * 按照字段查询
	 * @param field 字段名称
	 * @param value 字段值
	 * @return
	 */
	@Override
	public List<E> selectByField(Enum field, Object value)
	{
		return selectByField( field ,value ,null );
	}

	/** 
	 * 按照字段查询
	 * @param field 字段名称
	 * @param value 字段值
	 * @param page 分页
	 * @return
	 */
	@Override
	public List<E> selectByField(Enum field, Object value, Page page)
	{
		List<E> answer = null;
		answer = selectList( getTableName() + "." + field + "=? " ,page ,new Object[]
		{ value } );
		return answer;
	}

	/** 
	 * 按照多个字段与查询,字段数量和值的数量要一致.
	 * @param field 字段名称
	 * @param value 字段值
	 * @return
	 */
	@Override
	public List<E> selectByFields(Enum[] fields, Object[] values)
	{
		return selectByFields( fields ,values ,null );
	}

	/** 
	 * 按照多个字段与查询,字段数量和值的数量要一致.
	 * @param field 字段名称
	 * @param value 字段值
	 * @param page 分页
	 * @return
	 */
	@Override
	public List<E> selectByFields(Enum[] fields, Object[] values, Page page)
	{
		List<E> answer = null;
		if ( fields.length != values.length )
		{
			throw new RuntimeException( "查询字段数量和值不一致" );
		}
		StringBuilder condtion = new StringBuilder();
		boolean bool = false;
		for ( int i = 0 ; i < fields.length ; i++ )
		{
			if ( bool ) condtion.append( "AND " );
			else bool = true;
			condtion.append( getTableName() ).append( '.' ).append( fields[i] ).append( "=? " );
		}
		answer = selectList( condtion.toString() ,null ,values );
		return answer;
	}

	@Override
	public E selectOneByDynamic(Condition<? extends GeneratedCriteria> search)
	{
		String condtion = null;
		Object[] params = null;
		if ( search != null && search.getOredCriteria().size() > 0 )
		{
			Object[] build = make( search );
			condtion = (String) build[0];
			params = (Object[]) build[1];
		}
		return selectOne( condtion ,params );
	}

	@Override
	public int deleteByDynamic(Condition<? extends GeneratedCriteria> search)
	{
		String condtion = null;
		Object[] params = null;
		if ( search != null && search.getOredCriteria().size() > 0 )
		{
			Object[] build = make( search );
			condtion = (String) build[0];
			params = (Object[]) build[1];
		}
		return delete( condtion ,params );
	}

	@Override
	public int deleteByPrimaryKey(PK pk)
	{
		return delete( getFieldPrimaryKeyName() + "=? " ,new Object[]
		{ pk } );
	}

	@Override
	public int delete(PK pk)
	{
		return deleteByPrimaryKey( pk );
	}

	protected final int delete(String condtion, Object[] params)
	{
		int answer = 0;
		StringBuilder sql = new StringBuilder( "DELETE FROM " ).append( getTableName() );
		if ( params == null && params.length == 0 )
		{
			condtion = null;
			params = null;
			return answer;
		}
		if ( condtion != null )
		{
			sql.append( " WHERE " ).append( condtion );
		}
		try
		{
			answer = update( prepareConnection() ,true ,sql.toString() ,null ,params );
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
		}
		return answer;
	}

	protected final E selectOne(String condtion, Object[] params)
	{
		E answer = null;
		List<E> list = selectList( condtion ,new Page( 0, 1, 1 ) ,params );
		if ( list.size() > 0 ) answer = list.get( 0 );
		return answer;
	}

	protected final List<E> selectList(String condtion, Page page, Object[] params)
	{
		return selectList( null ,condtion ,page ,params );
	}

	protected final List<E> selectList(ResultSetHandler resultSetHandler, String condtion, Page page, Object[] params)
	{
		List<E> answer = null;
		final ResultSetHandler handler = resultSetHandler;
		StringBuilder sql = new StringBuilder( "SELECT " );
		StringBuilder sb = new StringBuilder( appendAvailableCondtion() );
		sql.append( getBaseQueryField() ).append( "FROM " ).append( getTableName() ).append( ' ' );
		if ( params == null || params.length == 0 )
		{
			condtion = null;
			params = null;
		}
		if ( condtion != null )
		{
			if ( sb.length() > 0 ) sb.append( "AND " );
			sb.append( condtion );
		}
		if ( sb.length() > 0 )
		{
			sql.append( "WHERE " ).append( sb );
		}
		if ( page == null )
		{
			page = new Page();
		}
		String orderby = page.getOrderBy();
		if ( orderby != null )
		{
			sql.append( "ORDER BY " ).append( getTableName() ).append( '.' ).append( orderby ).append( ' ' );
		}
		int total = page.getTotal();
		final int interval = page.getInterval();
		if ( total >= 0 )
		{
			sql.append( "LIMIT " ).append( page.getBegin() ).append( ',' ).append( page.getInterval() );
		}
		try
		{
			Connection conn = prepareConnection();
			answer = (List<E>) query( conn ,total != 0 ,false ,sql.toString() ,new ResultSetHandler()
			{

				@Override
				public List<E> handle(ResultSet resultSet, boolean hasBlob) throws SQLException
				{
					ResultSetHandler h = handler;
					if ( h == null )
					{
						h = getResultSetHandler();
					}
					List<E> answer = new ArrayList<E>( interval <= 0 ? Page.PAGE_COUNT : interval );
					E result = null;
					while ( (result = (E) h.handle( resultSet ,hasBlob )) != null )
					{
						answer.add( result );
					}
					return answer;
				}
			} ,params );
			if ( total == 0 )
			{
				StringBuilder countsql = new StringBuilder( "SELECT count(*) FROM " ).append( getTableName() ).append( ' ' );
				if ( sb.length() > 0 )
				{
					countsql.append( "WHERE " ).append( sb );
				}
				int count = (Integer) query( conn ,true ,false ,countsql.toString() ,new ResultSetHandler()
				{

					@Override
					public Object handle(ResultSet resultSet, boolean hasBlob) throws SQLException
					{
						Integer answer = 0;
						if ( resultSet.next() )
						{
							answer = resultSet.getInt( 1 );
						}
						return answer;
					}
				} ,params );
				page.setTotal( count );
			}
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
		}
		return answer;
	}

	protected int update(String set, String condtion, Object[] params)
	{
		int answer = 0;
		StringBuilder sql = new StringBuilder( "UPDATE " ).append( getTableName() ).append( " SET " ).append( set );
		StringBuilder sb = new StringBuilder( appendAvailableCondtion() );
		if ( condtion != null )
		{
			if ( sb.length() > 0 ) sb.append( "AND " );
			sb.append( condtion );
		}
		if ( sb.length() > 0 )
		{
			sql.append( "WHERE " ).append( sb );
		};
		try
		{
			answer = update( prepareConnection() ,true ,sql.toString() ,null ,params );
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
		}
		return answer;
	}

	protected Object[] make(Condition<? extends GeneratedCriteria> search)
	{
		Object[] answer = new Object[]
		{ (String) null, (Object[]) null };
		if ( search != null )
		{
			List<?> list = search.getOredCriteria();
			StringBuilder condtion = new StringBuilder();
			List params = new ArrayList();
			boolean or = false, and = false;
			GeneratedCriteria gc = null;
			for ( int i = 0 ; i < list.size() ; i++ )
			{
				gc = (GeneratedCriteria) list.get( i );
				if ( or )
				{
					condtion.append( "OR " );
					and = false;
				}
				else or = true;
				List<Criterion> lc = gc.getCriteria();
				for ( Criterion criterion : lc )
				{
					if ( and ) condtion.append( "AND " );
					else and = true;
					condtion.append( getTableName() ).append( '.' ).append( criterion.getCondition() );
					if ( criterion.getNoValue() )
					{
						continue;
					}
					if ( criterion.getSingleValue() )
					{
						if ( !criterion.getListValue() )
						{
							condtion.append( "? " );
							params.add( criterion.getValue() );
						}
						else
						{
						}
						continue;
					}
					if ( criterion.getBetweenValue() )
					{
						condtion.append( "? AND ? " );
						params.add( criterion.getValue() );
						params.add( criterion.getSecondValue() );
					}
				}
			}
			answer[0] = condtion.toString();
			answer[1] = params.toArray();
		}
		return answer;
	}

	protected String appendAvailableCondtion()
	{
		return "";
	}

	/** 
	 * 返回表的名称
	 * @return  String
	 */
	protected abstract String getTableName();

	protected abstract String getFieldPrimaryKeyName();

	protected abstract ResultSetHandler getResultSetHandler();

	protected abstract String getBaseQueryField();

	protected abstract String getBlobQueryField();

	protected abstract String[] getBaseField();

	protected abstract String[] getBlobField();

	protected abstract E getEntity(boolean hasBlob);

	/** 
	 * 默认不支持关联查询,如果子类支持请覆盖本方法.
	 */
	@Override
	public boolean isSupportAssociationQuery()
	{
		return false;
	}

	@Override
	public List<E> selectAllForAssociation()
	{
		return selectAll();
	}

	@Override
	public List<E> selectAllForAssociation(Page page)
	{
		return selectAll( page );
	}

	@Override
	public E selectByPrimaryKeyForAssociation(PK pk)
	{
		return selectByPrimaryKey( pk );
	}

	@Override
	public List<E> selectByFieldForAssociation(Enum field, Object value, Page page)
	{
		return selectByField( field ,value ,page );
	}

	@Override
	public List<E> selectByFieldForAssociation(Enum field, Object value)
	{
		return selectByField( field ,value );
	}

	@Override
	public List<E> selectByFieldsForAssociation(Enum[] fields, Object[] values)
	{
		return selectByFields( fields ,values );
	}

	@Override
	public List<E> selectByFieldsForAssociation(Enum[] fields, Object[] values, Page page)
	{
		return selectByFields( fields ,values ,page );
	}

	@Override
	public List<E> selectByDynamicForAssociation(Condition<? extends GeneratedCriteria> search)
	{
		return selectByDynamic( search );
	}

	@Override
	public List<E> selectByDynamicForAssociation(Condition<? extends GeneratedCriteria> search, Page page)
	{
		return selectByDynamic( search ,page );
	}
}
/* Honey v3.1 Test - version:1 - OriginalChecksum:Ba987a2f5648fedd6e326824c8f6f8dc5 (do not edit this line) */
